package com.example.springboot.RabbitMQ;

import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.sql.Array;
import java.util.ArrayList;

@Slf4j
@Component
public class TestConsumer_01 {

    private static final String exchangeName = "exchange_Direct_01";
    private static final String exchangeDieName = "exchange_die_01";
    private static final String queueName_01 = "queue_Direct_01";
    private static final String queueName_02 = "queue_Direct_02";
    private static final String queueName_die_01 = "queue_die_01";
    private static final String routingKey_01 = "routingKey_Direct_01";
    private static final String routingKey_02 = "routingKey_Direct_02";
    private static final String routingKey_die_01 = "routingKey_die_01";

    // 写法一、消费者端注解可以在RabbitMQ上创建交换机、队列
//    @RabbitListener(
//            bindings = @QueueBinding(
//                    value = @Queue(value = queueName_01, durable = "ture", arguments = @Argument(name = "x-message-ttl", value = "5000", type = "java.lang.Long ")),
//                    exchange = @Exchange(value = exchangeName , type = "direct"),
//                    key = {routingKey_01}
//            )
//    )
    // 写法二、只监听
//    @RabbitListener(queues = {queueName_01})
    public void receive_01(String dataString, Message message, Channel channel) throws IOException {

            log.info("消费者接收到的消息是：" + dataString);

    }

    // 手动确认消息模式，需先在配置文件中配置spring.rabbitmq.listener.simple.acknowledge-mode=manual
//    @RabbitListener(queues = {queueName_01})
    public void receive_02(String dataString, Message message, Channel channel) throws IOException {

        // 获取消息的DeliveryTag（rabbitmq生成的消息的唯一标识ID）
        long messageDeliveryTag = message.getMessageProperties().getDeliveryTag();

        try {

            //业务操作
            log.info("消费者接收到的消息是：" + dataString);

//            int i = 10/0 ;

            /**
             * 业务操作成功，返回ACK信息
             * 第一个参数为消息的DeliveryTag（rabbitmq生成的消息的唯一标识ID）
             * 第二个参数为是否批量操作
             */
            channel.basicAck(messageDeliveryTag,false);

        } catch (Exception e) {

             // 获取当前消息是否为重复投递
             boolean isRedelivered = message.getMessageProperties().getRedelivered();

            if (isRedelivered) {
                /**
                 * 业务操作失败，返回Nack信息
                 * 第一个参数为消息的DeliveryTag（rabbitmq生成的消息的唯一标识ID）
                 * 第二个参数为是否批量操作
                 * 第三个参数为是否将消息重新放回队列
                 */
                channel.basicNack(messageDeliveryTag,false,false);
            } else {
                channel.basicNack(messageDeliveryTag,false,true);

                /**
                 * 业务操作失败，返回Nack信息
                 * 第一个参数为消息的DeliveryTag（rabbitmq生成的消息的唯一标识ID）
                 * 第二个参数为是否将消息重新放回队列
                 * 与channel.basicNack()的区别是不能批量操作
                 */
//                channel.basicReject(messageDeliveryTag, true);

            }

            throw new RuntimeException(e);
        }

    }

    // 测试消费者端限流 (配置文件中配置spring.rabbitmq.listener.simple.prefetch=5)
    // 测试消息超时（队列层面） （rabiitMQ创建队列时，设置Arguments:(x-message-ttl = 5000)，5秒超时 ）或在使用注解创建队列时设置：arguments = @Argument(name = "x-message-ttl", value = "5000", type = "java.lang.Long ")
    //
//    @RabbitListener(queues = {queueName_01})
    public void receive_03(String dataString, Message message, Channel channel) throws IOException, InterruptedException {

        // 获取消息的DeliveryTag（rabbitmq生成的消息的唯一标识ID）
        long messageDeliveryTag = message.getMessageProperties().getDeliveryTag();

        Thread.sleep(1000);

        channel.basicAck(messageDeliveryTag,false);

        log.info("消费者接收到的消息是：" + dataString);



    }

    // 测试死信队列 创建死信队列，与普通队列设置没有什么不同
//    @RabbitListener(
//            bindings = @QueueBinding(
//                    value = @Queue(value = queueName_die_01, durable = "ture"),
//                    exchange = @Exchange(value = exchangeDieName),
//                    key = {routingKey_die_01}
//            )
//    )
    public void receive_04(String dataString, Message message, Channel channel) throws IOException {

        log.info("消费者接收到的消息是：" + dataString);

    }

    // 测试死信队列，创建正常队列，绑定死信队列，
    // 需要配置x-dead-letter-exchange和x-dead-letter-routing-key
    // 配置x-max-length是为了把消息溢出到死心队列
//    @RabbitListener(
//            bindings = @QueueBinding(
//                    value = @Queue(
//                            value = queueName_02,
//                            durable = "ture",
//                            arguments = {
//                                    @Argument(name = "x-dead-letter-exchange", value = exchangeDieName, type = "java.lang.String"),
//                                    @Argument(name = "x-dead-letter-routing-key", value = routingKey_die_01, type = "java.lang.String"),
//                                    @Argument(name = "x-max-length", value = "10", type = "java.lang.Long")
//                            }
//                    ),
//                    exchange = @Exchange(value = exchangeName , type = "direct"),
//                    key = {routingKey_02}
//            )
//    )
    public void receive_05(String dataString, Message message, Channel channel) throws IOException {

        log.info("消费者接收到的消息是：" + dataString);

    }

}